import java.io.Serializable;
import java.rmi.RemoteException;
import javax.swing.JOptionPane;

import common_classes.AuctionPrimitiveData;
import common_classes.AuctionStates;
import common_classes.BidPriceData;
import common_classes.CustomerData;
import common_classes.WSEvent;
import FlexTrade.WSAdaptor;
import common_classes.ProviderData;

/*
 * Each object of this class refers to a auction that the customer
 * has joined. Customer will communicate with auction by this class
 */
public class Customer implements Serializable, Runnable {

	private static final long serialVersionUID = -4757774770772835854L;
	private static final long EVENT_RECEIVE_INTERVAL = 2000;
	private WSAdaptor service;
	private CustomerData customerData;
	private boolean stopThread = false;
	
	public javax.swing.JTextArea txtEventLog;

	public void stopEventThread() {
		stopThread = true;
	}
	
	public void setEventLog(javax.swing.JTextArea _txtEventLog) {
		this.txtEventLog = _txtEventLog;
	}
	
	public void setService(WSAdaptor _service) {
		this.service = _service;
	}
	
	public void setCustomerData(common_classes.CustomerData _customerData) {
		this.customerData = _customerData;
	}
	
	public void pullEvents(String _uniqueAuctionID) {
		AuctionStates finalAuctionStates;
		ProviderData auctionProviderData;
		WSEvent[] eventList = null;
		WSEvent t_event = null;
		int eventID = -1;
		int t_auctionType;
		String messageLog = "";
		String uniqueCustomerIDOfWinner = "";		//ID of customer who won the auction
		BidPriceData bidPriceData;				//information about customer who won auction and its bid price
		
		try {
			eventList = service.pullWSEvents(_uniqueAuctionID, this.customerData.getUniqueCustomerID());
			if (eventList == null) return;
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//the final status when the event occurs
		float winningPrice;
		for (int i = 0; i < eventList.length; i++) {
			t_event = eventList[i];
			finalAuctionStates = t_event.getAuctionStates();
			auctionProviderData = t_event.getAuctionPrimitiveData().getProvider();
			eventID = (int) t_event.getEventID();
			switch(eventID){
				case IAuction.E_NEW_AUCTION:
					messageLog = FlexTradeUtils.currentTime() + ": New English auction ID " + _uniqueAuctionID;
					messageLog = messageLog + "by provider " + auctionProviderData.getUniqueProviderID() + " has just created.";
					this.txtEventLog.append(messageLog + "\n");
					break;
				case IAuction.V_NEW_AUCTION:
					messageLog = FlexTradeUtils.currentTime() + ": New Vickrey auction ID " + _uniqueAuctionID;
					messageLog = messageLog + "by provider " + auctionProviderData.getUniqueProviderID() + " has just created.";
					this.txtEventLog.append(messageLog + "\n");
					break;
				case IAuction.D_NEW_AUCTION:
					messageLog = FlexTradeUtils.currentTime() + ": New Dutch auction ID " + _uniqueAuctionID;
					messageLog = messageLog + "by provider " + auctionProviderData.getUniqueProviderID() + " has just created.";
					this.txtEventLog.append(messageLog + "\n");
					break;
			
				case IAuction.E_AUCTION_FINISH:
					//get ID of customer who won the bid from remote auction object
					uniqueCustomerIDOfWinner = finalAuctionStates.getHighestBidCustomer().getUniqueCustomerID();
					winningPrice = finalAuctionStates.getHighestBidPrice();
					if(uniqueCustomerIDOfWinner.equals(customerData.getUniqueCustomerID())) {	//if you won
						messageLog = FlexTradeUtils.currentTime() + ": Congratulation. You won auction of ID:" + 
								_uniqueAuctionID;
						messageLog = messageLog + " with price " + Float.toString(winningPrice);
						JOptionPane.showMessageDialog(null, messageLog, "Auction finished",JOptionPane.OK_CANCEL_OPTION);
						//tranfer money to provider
						try {
							service.paymentTransfer(_uniqueAuctionID, 
													winningPrice, 
													uniqueCustomerIDOfWinner, 
													auctionProviderData.getUniqueProviderID());
						} catch (RemoteException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					} else {	//you lost this auction
						messageLog = FlexTradeUtils.currentTime() + "Auction ID " + _uniqueAuctionID + " is finished";
						messageLog = messageLog + ". Winning price is " + Float.toString(winningPrice);
					}
					//display logging information to text area in main frame UI
					this.txtEventLog.append(messageLog + "\n");
					break;
				
				case IAuction.E_BID_PRICE_RECEIVED:
					//get the last bid that placed in this auction
					bidPriceData = t_event.getLastBidPriceData();
					messageLog = FlexTradeUtils.currentTime() + ": Received a bid price of " + bidPriceData.getBidPrice() + " from ";
					messageLog = messageLog + "customer " + bidPriceData.getCustomer().getUniqueCustomerID();
					messageLog = messageLog + " for aution ID " + _uniqueAuctionID;
					this.txtEventLog.append(messageLog + "\n");
					break;
	
				case IAuction.E_CUSTOMER_JOIN:
					messageLog = FlexTradeUtils.currentTime() + ": A new customer has joined the auction :" +
																_uniqueAuctionID;
					this.txtEventLog.append(messageLog + "\n");;
					break;
				
				case IAuction.V_AUCTION_FINISH:
					uniqueCustomerIDOfWinner = finalAuctionStates.getHighestBidCustomer().getUniqueCustomerID();
					//in Vickrey, customer winning the bid would pay the second highest price
					winningPrice = finalAuctionStates.getSecondHighestBidPrice();
					if(uniqueCustomerIDOfWinner.equals(customerData.getUniqueCustomerID())) {	//if you won
						messageLog = FlexTradeUtils.currentTime() + ": Congratulation. You won auction :" + 
								_uniqueAuctionID;
						messageLog = messageLog + " with price " + Float.toString(winningPrice); 
						JOptionPane.showMessageDialog(null, messageLog, "Auction finished",JOptionPane.OK_CANCEL_OPTION);
						try {
							service.paymentTransfer(_uniqueAuctionID, 
									winningPrice, 
									uniqueCustomerIDOfWinner, 
									auctionProviderData.getUniqueProviderID());
						} catch (RemoteException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					} else {	//if you lost this auction
						messageLog = FlexTradeUtils.currentTime() + ": Auction " + _uniqueAuctionID + " is finished";
						messageLog = ". Winning price is " + Float.toString(finalAuctionStates.getHighestBidPrice());
					}
					this.txtEventLog.append(messageLog + "\n");;
					break;
				
				case IAuction.V_BID_PRICE_RECEIVED:
					//do nothing. In Vickrey auction, customer will not be informed about the other customers' information
					break;
				
				case IAuction.V_CUSTOMER_JOIN:
					//do nothing. In Vickrey auction, customer will not be informed about the other customers' information
					break;
				
				case IAuction.D_AUCTION_FINISH:
					//do nothing
					break;
				
				case IAuction.D_ACCEPTABLE_PRICE_RECEIVED:
					messageLog = FlexTradeUtils.currentTime() + ": Received new offer from auction ID:" + _uniqueAuctionID;
					messageLog = messageLog + " with price of " + Float.toString(finalAuctionStates.getAcceptableBidPrice());
					messageLog = messageLog + ". Press join auction button to accept.";
					/*
					int reply = JOptionPane.showConfirmDialog(null, messageLog, "New Offer Received", JOptionPane.YES_NO_OPTION);
					if(reply == JOptionPane.YES_OPTION){	//accept this offer
						//check this again
						BidPriceData _bidPriceData = new BidPriceData();
						_bidPriceData.setCustomer(this.customerData);
						_bidPriceData.setBidPrice(finalAuctionStates.getAcceptableBidPrice());
						try {
							service.receivePriceAcceptanceFromCustomer(_uniqueAuctionID, _bidPriceData);
						} catch (RemoteException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						//sourceAuction.receivePriceAcceptanceFromCustomer(_bidPriceData);
					} else {
						messageLog = FlexTradeUtils.currentTime() + ": Received new offer of "  
											+ Float.toString(finalAuctionStates.getAcceptableBidPrice());
						messageLog = messageLog + " for auction " + _uniqueAuctionID;
					}
					*/
					//refresh the price value in auction table of main UI
					this.txtEventLog.append(messageLog + "\n");;
					//customerUI.refreshAuctionsTable();
					break;
			
				case IAuction.D_CUSTOMER_JOIN:
					//do nothing
					break;
	
				case IAuction.D_CUSTOMER_ACCEPT:
					uniqueCustomerIDOfWinner = finalAuctionStates.getHighestBidCustomer().getUniqueCustomerID();
					winningPrice = finalAuctionStates.getAcceptableBidPrice();
					messageLog = FlexTradeUtils.currentTime() + ": Customer " + uniqueCustomerIDOfWinner + " has accepted ";
					messageLog = messageLog + " offer of " + Float.toString(winningPrice) + " from provider ";
					messageLog = messageLog + auctionProviderData.getUniqueProviderID();
					//transfer money here
					this.txtEventLog.append(messageLog + "\n");;
				try {
					service.paymentTransfer(_uniqueAuctionID, 
							winningPrice, 
							uniqueCustomerIDOfWinner, 
							auctionProviderData.getUniqueProviderID());
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
					break;
	
				case IAuction.CANNOT_TRANSFER_PAYMENT:
					uniqueCustomerIDOfWinner = finalAuctionStates.getHighestBidCustomer().getUniqueCustomerID();
					//only show log about payment to customer/provider involve in this transaction
					if(uniqueCustomerIDOfWinner.equals(customerData.getUniqueCustomerID()) == false){
						break;
					}
					t_auctionType = t_event.getAuctionPrimitiveData().getAuctionType();
					if(t_auctionType == IAuction.ENGLISH_AUCTION_TYPE){
						winningPrice = finalAuctionStates.getHighestBidPrice();
					} else if(t_auctionType == IAuction.VICKREY_AUCTION_TYPE){
						winningPrice = finalAuctionStates.getSecondHighestBidPrice();
					} else if(t_auctionType == IAuction.DUTCH_AUCTION_TYPE) {
						winningPrice = finalAuctionStates.getAcceptableBidPrice();
					} else {
						winningPrice = 0;
					}
					messageLog = FlexTradeUtils.currentTime() + ": Error. Payment of " + Float.toString(winningPrice) + " cannot be transfered ";
					messageLog = messageLog + "from customer " + uniqueCustomerIDOfWinner + " bank account to provider ";
					messageLog = messageLog + auctionProviderData.getUniqueProviderID() + " bank account";
					this.txtEventLog.append(messageLog + "\n");;
					break;
				
				case IAuction.PAYMENT_TRANSFERED_SUCCESSFULLY:
					uniqueCustomerIDOfWinner = finalAuctionStates.getHighestBidCustomer().getUniqueCustomerID();
					//only show log about payment to customer/provider involve in this transaction
					if(uniqueCustomerIDOfWinner.equals(customerData.getUniqueCustomerID()) == false){
						break;
					}
					t_auctionType = t_event.getAuctionPrimitiveData().getAuctionType();
					if(t_auctionType == IAuction.ENGLISH_AUCTION_TYPE){
						winningPrice = finalAuctionStates.getHighestBidPrice();
					} else if(t_auctionType == IAuction.VICKREY_AUCTION_TYPE){
						winningPrice = finalAuctionStates.getSecondHighestBidPrice();
					} else if(t_auctionType == IAuction.DUTCH_AUCTION_TYPE) {
						winningPrice = finalAuctionStates.getAcceptableBidPrice();
					} else {
						winningPrice = 0;
					}
					messageLog = FlexTradeUtils.currentTime() + ": Payment of " + Float.toString(winningPrice) + " has been transfered successfully ";
					messageLog = messageLog + "from customer " + uniqueCustomerIDOfWinner + " bank account to provider ";
					messageLog = messageLog + auctionProviderData.getUniqueProviderID() + " bank account";
					this.txtEventLog.append(messageLog + "\n");;
					break;
					
				case(IAuction.D_AUCTION_TIMEOUT):
					//do nothing
					break;
				
				default:
					System.out.println("Invalid event ID occurs" + Integer.toString(eventID));
					return;
			}
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		AuctionPrimitiveData[] listOfAuctions = null;
		while (!stopThread) {
			try {
				Thread.sleep(EVENT_RECEIVE_INTERVAL);
				listOfAuctions = service.getCurrentActiveAuctions();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (listOfAuctions != null) {
				for (int i = 0; i < listOfAuctions.length; i++) {
					pullEvents(listOfAuctions[i].getUniqueAuctionID());
				}
			}
		}
	}
}
